<template>
  <div class="bs-upload">
    <el-upload
      ref="upload"
      drag
      :action="uploadImgUrl"
      :before-upload="handleBeforeUpload"
      name="file"
      :headers="headers"
      :limit="1"
      :on-change="handleRemove"
      :on-remove="handleRemove"
      :file-list="fileList"
      :auto-upload="false"
    >
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
      <!-- 上传提示 -->
      <div class="el-upload__tip" slot="tip" v-if="showTip">

        <template v-if="fileSize">
          请上传大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>格式为 <b style="color: #f56c6c"
        >{{ fileType.join('/') }}</b> 的文件。
        </template>
        <el-button size="small" type="success" @click="submitUpload"
                   v-loading.fullscreen="fullscreenLoading"
                   element-loading-spinner="el-icon-loading"
                   element-loading-text="正在上传，请勿关闭..."
        >上传到服务器
        </el-button>

      </div>
    </el-upload>


    <el-progress v-if="percentage > 0" class="result-process" :percentage="percentage"></el-progress>
  </div>
</template>

<script>
import { getToken } from '@/utils/auth'
import api from '@/api/upload'

export default {
  name: 'UploadChunk',
  props: {
    // 大小限制(MB)
    fileSize: {
      type: Number,
      default: 50
    },
    // 文件类型, 例如['png', 'jpg', 'jpeg']
    fileType: {
      type: Array,
      default: () => ['png', 'jpg', 'jpeg']
    },
    // 是否显示提示
    isShowTip: {
      type: Boolean,
      default: true
    },
    // 分片大小限制(MB)
    fileChunkSize: {
      type: Number,
      default: 1
    }
  },
  data() {
    return {
      fullscreenLoading: false,
      baseUrl: '',
      uploadImgUrl: '', // 上传的图片服务器地址
      headers: {
        Authorization: 'Bearer ' + getToken(),
        'Content-Type': 'multipart/form-data'
      },
      successCount: 0, // 成功上传的分片数
      chunkSize: 1024 * 1024 * this.fileChunkSize, // 分片大小（1MB）
      percentage: 0,
      fileList: []
    }
  },
  computed: {
    // 是否显示提示
    showTip() {
      return this.isShowTip && (this.fileType || this.fileSize)
    }
  },
  methods: {
    // 上传前文件校验
    handleBeforeUpload(file) {
      this.percentage = 0
      this.successCount = 0

      // 校验文件
      let fileTypeValid = false
      if (this.fileType.length) {
        let fileExtension = ''
        if (file.name.lastIndexOf('.') > -1) {
          fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
        }
        fileTypeValid = this.fileType.some((type) => {
          if (file.type.indexOf(type) > -1) return true
          if (fileExtension && fileExtension.indexOf(type) > -1) return true
          return false
        })
      } else {
        fileTypeValid = file.type.indexOf('image') > -1
      }

      if (!fileTypeValid) {
        this.$message.error(`文件格式不正确, 请上传${this.fileType.join('/')}格式文件!`)
        return false
      }

      if (this.fileSize) {
        const isLt = file.size / 1024 / 1024 < this.fileSize
        if (!isLt) {
          this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`)
          return false
        }
      }

      // 分片逻辑
      const totalChunks = Math.ceil(file.size / this.chunkSize)
      let currentChunk = 0
      this.fullscreenLoading = true
      let full_url = '';
      // 依次上传每个分片
      const uploadNextChunk = () => {
        this.percentage = Math.round(currentChunk / totalChunks * 100)
        if (currentChunk >= totalChunks) {
          this.$message.success('上传完成')
          this.percentage = 100
          this.$emit('uploaded', full_url)
          this.fullscreenLoading = false
          console.log('上传完成', 'x')
          return
        }

        const chunk = file.slice(
          currentChunk * this.chunkSize,
          currentChunk === totalChunks - 1 ? file.size : (currentChunk + 1) * this.chunkSize
        )

        const formData = new FormData()
        formData.append('file', chunk)
        formData.append('chunkNumber', currentChunk + 1)
        formData.append('totalChunks', totalChunks)
        formData.append('filename', file.name)
        api.chunk(formData)
          .then(response => {
            if (response.code === 0) {
              this.successCount++
              currentChunk++
              if (currentChunk >= totalChunks) {
                console.log('上传完成', 'y')
                full_url = response.data.full_url
              }
              uploadNextChunk() // 递归调用继续上传下一个分片
            }
          })
          .catch(error => {
            console.log('上传失败', error)
            this.$message({
              type: 'error',
              message: '上传失败'
            })
            this.fullscreenLoading = false
            throw error // 抛出错误以便后续处理
          }).finally(() => {

        })
      }

      uploadNextChunk()
      return false // 阻止 el-upload 的默认上传行为
    },
    submitUpload() {

      if (this.fileList.length === 0) {
        this.$message({
          type: 'error',
          message: '请先选择需要上传的文件'
        })
        return
      }
      this.$refs.upload.submit()
    },
    handleRemove(file, fileList) {
      this.fileList = fileList
      this.successCount = 0
      this.percentage = 0
    }
  }
}
</script>

<style scoped lang="scss">
.result-process {
  z-index: 999999;
}

.bs-upload {
  width: 90%;
}
</style>
